package com.abc.config.security;

import com.abc.model.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;

import javax.servlet.Filter;

@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsServiceImpl;
    @Autowired
    private JwtTokenService jwtTokenService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 登录拦截相关配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests().anyRequest().authenticated()

                .and().exceptionHandling()
                .accessDeniedHandler(needAuthorityHandler())
                .authenticationEntryPoint(needLoginHandler())

                .and().addFilter(jsonLoginFilter())
                .addFilterAfter(new JwtTokenFilter(jwtTokenService), LoginFilter.class)
                .userDetailsService(userDetailsServiceImpl);
    }

    /**
     * 如果一个请求认证了但没有访问权限时触发的回调函数
     */
    public AccessDeniedHandler needAuthorityHandler(){
        return (req,res,ex) -> {
            Result json = Result.error("filter").msg("没有权限").data("exception",ex.getMessage());
            res.setStatus(403);
            res.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            res.getWriter().write(json.toString());
        };
    }

    /**
     * 如果一个请求需要认证时触发的回调函数
     */
    public AuthenticationEntryPoint needLoginHandler(){
        return (req,res,ex) -> {
            Result json = Result.error("filter").msg("请先登录").data("exception",ex.getMessage());
            res.setStatus(401);
            res.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            res.getWriter().write(json.toString());
        };
    }

    /**
     * json中获取username, password执行登录操作
     * @return
     * @throws Exception
     */
    @Bean
    public Filter jsonLoginFilter() throws Exception {
        LoginFilter filter = new LoginFilter();
        //这句很关键，重用WebSecurityConfigurerAdapter配置的AuthenticationManager，不然要自己组装AuthenticationManager
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }


}
